package other.edan.intlpass.utils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * ClassName: DateTools
 * Description: 日期时间工具类
 * date: 2023/5/22
 *
 * @author Arende
 */
public class DateTools {

    private static final DateTimeFormatter DTF_DATETIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DTF_DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date dateNow() {
        Instant ins = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 获取自定义日期
     *
     * @param year
     * @param month
     * @param day
     * @return
     */
    public static Date currentDate(int year, int month, int day) {
        LocalDate ld = LocalDate.of(year, month, day);
        Instant ins = ld.atStartOfDay(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 获取自定义日期时间
     *
     * @param year
     * @param month
     * @param day
     * @param hour
     * @param minute
     * @param second
     * @return
     */
    public static Date currentDate(int year, int month, int day, int hour, int minute, int second) {
        LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
        Instant ins = ldt.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 日期转字符串
     *
     * @param date
     * @param pattern 自定义格式化
     * @return
     */
    public static String dateToString(Date date, String pattern) {
        Instant ins = date.toInstant();
        LocalDateTime ldt = LocalDateTime.ofInstant(ins, ZoneId.systemDefault());
        return ldt.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * LocalDateTime --> String
     *
     * @param date
     * @return
     */
    public static String localDateTimeToString(LocalDateTime date) {
        return date.format(DTF_DATETIME);
    }

    /**
     * Date --> LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        return LocalDateTime.ofInstant(instant, zone);
    }

    /**
     * Date --> LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.toLocalDate();
    }

    /**
     * Date --> .LocalTime
     *
     * @param date
     * @return
     */
    public static LocalTime dateToLocalTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.toLocalTime();
    }

    /**
     * LocalDateTime --> Date
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * LocalDate --> Date
     *
     * @param localDate
     * @return
     */
    public static Date localDateToDate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * LocalTime --> Date
     *
     * @param localTime
     * @return
     */
    public static Date localTimeToDate(LocalTime localTime) {
        LocalDate localDate = LocalDate.now();
        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * 字符串转日期 yyyy-MM-dd HH:mm:ss
     *
     * @param fromDate yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static Date toDateTime(String fromDate) {
        LocalDateTime ldt = LocalDateTime.parse(fromDate, DTF_DATETIME);
        Instant ins = ldt.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 字符串转日期
     *
     * @param fromDate 数据字符串
     * @param pattern  自定义数据格式
     * @return
     */
    public static Date toDateTime(String fromDate, String pattern) {
        LocalDateTime ldt = LocalDateTime.parse(fromDate, DateTimeFormatter.ofPattern(pattern));
        Instant ins = ldt.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 字符串转日期 yyyy-MM-dd
     *
     * @param fromDate yyyy-MM-dd
     * @return
     */
    public static Date toDate(String fromDate) {
        LocalDate ld = LocalDate.parse(fromDate, DTF_DATE);
        Instant ins = ld.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 获取当天开始时间
     *
     * @param date
     * @return
     */
    public static Date dayStartTime(Date date) {
        Instant ins = date.toInstant();
        ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault()).withHour(0).withMinute(0).withSecond(0);
        return Date.from(zdt.toInstant());
    }

    /**
     * 获取当天结束时间
     *
     * @param date
     * @return
     */
    public static Date dayEndTime(Date date) {
        Instant ins = date.toInstant();
        ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault()).withHour(23).withMinute(59).withSecond(59);
        return Date.from(zdt.toInstant());
    }

    /**
     * 获取当月的开始时间
     *
     * @param date
     * @return
     */
    public static Date mothStartTime(Date date) {
        Instant ins = date.toInstant();
        ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault()).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        return Date.from(zdt.toInstant());
    }

    /**
     * 获取当月的结束时间
     *
     * @param date
     * @return
     */
    public static Date mothEndTime(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int max = c.getActualMaximum(Calendar.DATE);//最大天数
        ZonedDateTime zdt = c.toInstant().atZone(ZoneId.systemDefault()).withDayOfMonth(max).withHour(23).withMinute(59).withSecond(59);
        return Date.from(zdt.toInstant());
    }

    /**
     * 计算日期差 end - start
     *
     * @param start
     * @param end
     * @return
     */
    public static int differDate(Date start, Date end) {
        Instant startIns = start.toInstant();
        Instant endIns = end.toInstant();
        int startday = startIns.atZone(ZoneId.systemDefault()).getDayOfYear();
        int endday = endIns.atZone(ZoneId.systemDefault()).getDayOfYear();
        return endday - startday;
    }

    /**
     * 追加天数
     *
     * @param day
     * @param now
     * @return
     */
    public static Date addDay(int day, Date now) {
        LocalDateTime ldt = LocalDateTime.now();
        if (null != now) {
            ldt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
        }
        ldt = ldt.plusDays(day);
        Instant ins = ldt.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 追加月份
     *
     * @param months
     * @param now
     * @return
     */
    public static Date addMonth(int months, Date now) {
        LocalDateTime ldt = LocalDateTime.now();
        if (null != now) {
            ldt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
        }
        ldt = ldt.plusMonths(months);
        Instant ins = ldt.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 追加年份
     *
     * @param year
     * @param now
     * @return
     */
    public static Date addYear(int year, Date now) {
        LocalDateTime ldt = LocalDateTime.now();
        if (null != now) {
            ldt = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
        }
        ldt = ldt.plusYears(year);
        Instant ins = ldt.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(ins);
    }

    /**
     * 传入Date型时间，传出yyyy-mm-dd格式字符串
     *
     * @param update
     * @return
     */
    public static String dateOnly(Date update) {
        return dateToString(update, "yyyy-MM-dd");
    }

    /**
     * 获取当前日期是星期几
     *
     * @param fromDate 传入yyyy-MM-dd格式
     * @return 周一 周二 ... 周日
     */
    public static String getWeekByDay(String fromDate) {
        String[][] strArray = {{"MONDAY", "一"}, {"TUESDAY", "二"}, {"WEDNESDAY", "三"}, {"THURSDAY", "四"}, {"FRIDAY", "五"}, {"SATURDAY", "六"}, {"SUNDAY", "日"}};
        LocalDate currentDate = LocalDate.parse(fromDate, DTF_DATE);
        String k = String.valueOf(currentDate.getDayOfWeek());
        for (int i = 0; i < strArray.length; i++) {
            if (k.equals(strArray[i][0])) {
                k = strArray[i][1];
                break;
            }
        }
        return "周" + k;
    }

    /**
     * 获取当前月份
     *
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH) + 1;
        return month;
    }

    /**
     * 获取下mon个月的日期
     *
     * @param time
     * @param mon
     * @return
     */
    public static Date getNextMonth(Date time, int mon) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.add(Calendar.MONTH, mon);
        return calendar.getTime();
    }

    /**
     * date --> long
     *
     * @param date
     * @return
     */
    public static long dateToLong(Date date) {
        return date.getTime();
    }

    /**
     * Long --> String
     *
     * @param time
     * @param formDate
     * @return
     */
    public static String longToString(Long time, String formDate) {
        Date date = new Date(time);
        return dateToString(date, formDate);
    }

    /**
     * String --> Long
     *
     * @param strTime
     * @param formatType
     * @return
     */
    public static long stringToLong(String strTime, String formatType) {
        Date dateTime = toDateTime(strTime, formatType);
        return dateTime.getTime();
    }

    /**
     * String --> Long
     * time format: yyyy-MM-dd HH:mm:ss
     *
     * @param strTime
     * @return
     */
    public static long dateTimeStrToLong(String strTime) {
        Date dateTime = toDateTime(strTime);
        return dateTime.getTime();
    }

    /**
     * String --> Long
     *
     * @param strDate
     * @return
     */
    public static long dateStrToLong(String strDate) {
        Date dateTime = toDate(strDate);
        return dateTime.getTime();
    }

    public static String getTimeStrFormat(String strTime) {
        StringBuilder dateFormat = new StringBuilder("yyyy-MM-dd HH:mm:ss");
        if (strTime.contains(".")) {
            String[] split = strTime.split("\\.");
            int length = split[1].length();
            dateFormat.append(".");
            for (int i = 0; i < length; i++) {
                dateFormat.append("S");
            }
        }
        return dateFormat.toString();
    }
}
